package com.beiding.jsonanalyzer.querylink;

import com.beiding.jsonanalyzer.analyze.Joiner;
import com.beiding.jsonanalyzer.analyze.KeyMode;
import com.beiding.jsonanalyzer.analyze.Window;
import com.beiding.jsonanalyzer.analyze.func.FuncBase;
import com.beiding.jsonanalyzer.analyze.func.FuncFactory;
import com.beiding.jsonanalyzer.analyze.map.BatchMapper;
import com.beiding.jsonanalyzer.analyze.map.Mapper;
import com.beiding.jsonanalyzer.analyze.query.ComparatorResult;
import com.beiding.jsonanalyzer.analyze.select.SelectPair;
import com.beiding.jsonanalyzer.analyze.select.SelectorBuilder;
import com.beiding.jsonanalyzer.flow.Branch;
import com.beiding.jsonanalyzer.flow.BranchNode;
import com.beiding.jsonanalyzer.flow.ComputeResource;
import com.beiding.jsonanalyzer.flow.ValueNode;

import java.util.function.Consumer;

/**
 * 查询执行链
 * 子句构造器
 * analyzer
 * .query()
 * .eq("name","张三")
 * .order()
 * .asc("name")
 * .desc("age")
 * .custom("age",new Sorter()...)
 * .group()
 * .by("name")
 * .join()
 * .left(...)
 * .fetch()
 * .fetch("name")
 * .fetch("age","a")
 * .exec() //执行触发点
 */
public interface QueryLinkNode<W extends ValueNode> extends BaseLinkNode<W> {


   /*
   去掉group操作,使用branch替代
   default GroupQueryLinkNode group() {
        return new GroupQueryLinkNode(this, KeyMode.TEXT_TO_KEY);
    }*/

    default FindQueryLinkNode<W> where(FuncFactory<FuncBase<ComparatorResult>> queryBuilder) {
        return new FindQueryLinkNode<>(this, queryBuilder);
    }

    /**
     * 命名
     *
     * @param key
     * @return
     */
    default NamedAsQueryLinkNode<W> nameAs(Object key) {
        return new NamedAsQueryLinkNode<>(this, key);
    }


    /**
     * 排序
     *
     * @return
     */
    default OrderQueryLinkNode<W> order() {
        return new OrderQueryLinkNode<>(this, KeyMode.TEXT_TO_KEY);
    }

    default RangeQueryLinkNode<W> range() {
        return new RangeQueryLinkNode<>(this);
    }

    default RangeQueryLinkNode<W> range(int from) {
        return range().from(from);
    }


    default RangeQueryLinkNode<W> range(int from, int length) {
        return range().from(from).length(length);
    }

    default CheckQueryLinkNode<W> check(FuncFactory<FuncBase<ComparatorResult>> checker) {
        return new CheckQueryLinkNode<>(this, checker);
    }

    default SelectQueryLinkNode<W> select(SelectPair... selectPairs) {
        SelectorBuilder selectorBuilder = new SelectorBuilder();
        for (SelectPair selectPair : selectPairs) {
            if (selectPair.getAlias() == null) {
                selectorBuilder.fetch(selectPair.getExp());
            } else {
                selectorBuilder.fetch(selectPair.getExp(), selectPair.getAlias());
            }
        }
        return new SelectQueryLinkNode<>(this, selectorBuilder);
    }


    default JoinQueryLinkNode<W> leftJoin(QueryLinkNode right) {
        return new JoinQueryLinkNode<W>(this, right) {

            @Override
            protected void doJoin(BranchNode<W> r, BranchNode<W> left, BranchNode<W> right, FuncBase<ComparatorResult> onCondition) {
                Joiner.leftJoin(r, left, right, onCondition);
            }
        };
    }

    default JoinQueryLinkNode<W> rightJoin(QueryLinkNode right) {
        return new JoinQueryLinkNode<W>(this, right) {

            @Override
            protected void doJoin(BranchNode<W> r, BranchNode<W> left, BranchNode<W> right, FuncBase<ComparatorResult> onCondition) {
                Joiner.rightJoin(r, left, right, onCondition);
            }
        };
    }

    default JoinQueryLinkNode<W> join(QueryLinkNode right) {
        return new JoinQueryLinkNode<W>(this, right) {

            @Override
            protected void doJoin(BranchNode<W> r, BranchNode<W> left, BranchNode<W> right, FuncBase<ComparatorResult> onCondition) {
                Joiner.join(r, left, right, onCondition);
            }
        };
    }

    default JoinQueryLinkNode<W> fullJoin(QueryLinkNode right) {
        return new JoinQueryLinkNode<W>(this, right) {

            @Override
            protected void doJoin(BranchNode<W> r, BranchNode<W> left, BranchNode<W> right, FuncBase<ComparatorResult> onCondition) {
                Joiner.outerJoin(r, left, right, onCondition);
            }
        };
    }


    /**
     * 转换节点
     * 传入一个表达式
     * 可以是
     * ValueExpression
     * Key
     * 如果是字符串将解析为key处理
     * 以下两种除外
     * ${表达式}
     * '字符串'
     *
     * @param exp
     * @return
     */
//    default TransformQueryLinkNode<W> toValue(Object exp) {
//        return new TransformQueryLinkNode<>(this, o -> Analyzer.get(o, KeyUtils.handleKey(exp, KeyMode.TEXT_TO_KEY), Object.class));
//    }

    /**
     * 结果集去重
     *
     * @return
     */
    default DistinctQueryLinkNode<W> distinct() {
        return new DistinctQueryLinkNode<W>(this);
    }

    default UnionQueryLinkNode<W> union(QueryLinkNode<W> queryLinkNode) {
        return new UnionQueryLinkNode<>(this, queryLinkNode, false);
    }

    default UnionQueryLinkNode<W> unionAll(QueryLinkNode<W> queryLinkNode) {
        return new UnionQueryLinkNode<>(this, queryLinkNode, true);
    }

/*

    default BranchByQueryLinkNode branchBy(Object key, ComputeResource<W> computeResource) {
        return new BranchByQueryLinkNode(this, KeyUtils.handleKey(key, KeyMode.TEXT_TO_KEY), computeResource);
    }

*/

    default BranchQueryLinkNode<W> branch(Object key) {
        return new BranchQueryLinkNode<>(this, key, null);
    }

    default BranchQueryLinkNode<W> branch(Object key, ComputeResource useComputeResourceQueryLinkNode) {
        return new BranchQueryLinkNode<>(this, key, useComputeResourceQueryLinkNode);
    }

//
//    default UseComputeResourceQueryLinkNode<W> useComputeResource(ComputeResource computeResource) {
//        return new UseComputeResourceQueryLinkNode<>(this, computeResource);
//    }

    default BreakPressureQueryLinkNode<W> breakPressure(int maxSize) {
        return new BreakPressureQueryLinkNode<>(this, maxSize);
    }

    /**
     * 可以使用时间或者数量控制窗口
     * 窗口会产生分批
     * join union order 等操作都是在一个分批中完成的
     *
     * @param window
     * @return
     */
    default WindowQueryLinkNode<W> window(Window window) {
        return new WindowQueryLinkNode<>(this, window);
    }

    default EachBranchQueryLinkNode<W> eachBranch(Consumer<Branch<W>> branchConsumer) {
        return new EachBranchQueryLinkNode<>(this, branchConsumer);
    }

    /**
     * 聚合映射
     *
     * @param batchMapper
     * @return
     */
    default AggMapQueryLinkNode<W> aggMap(BatchMapper<W> batchMapper) {
        return new AggMapQueryLinkNode<>(this, batchMapper);
    }


    /**
     * 简单映射
     *
     * @param mapper
     * @return
     */
    default MapQueryLinkNode<W> map(Mapper<W> mapper) {
        return new MapQueryLinkNode<>(this, mapper);
    }


}
